package org.dfl.plugin.views.actions;

import java.io.File;
import java.io.IOException;

import org.dfl.core.data.IODataManager;
import org.dfl.core.data.types.Type;
import org.dfl.core.data.types.TypeManager;
import org.dfl.core.utils.Utils;
import org.dfl.messages.Messages;
import org.dfl.plugin.DflPlugin;
import org.dfl.plugin.ProjectConstraints;
import org.dfl.plugin.dialogs.DialogsManager;
import org.dfl.plugin.utils.WorkbenchUtil;
import org.dfl.plugin.views.ViewsManager;
import org.dfl.plugin.views.debug.TreeElemPreview;
import org.dfl.plugin.views.debug.model.DataTreeElem;
import org.dfl.plugin.views.debug.model.MapKeyTreeElem;
import org.dfl.plugin.views.debug.model.TokenTreeElem;
import org.dfl.plugin.views.debug.model.TreeElem;
import org.dfl.plugin.views.debug.model.TreeElemFactory;
import org.dfl.plugin.views.debug.model.TreeElemImpl;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.ui.actions.ActionDelegate;

/**
 * action that provide loading a content to data or token objects. 
 * It's used in a HistoriesTreeView and TokensTreeView (see mapping in plugin.xml file)
 * @author Piotr Wlodarczyk
 *
 */
public class LoadContentAction extends ActionDelegate {
	
	private IStructuredSelection selection = StructuredSelection.EMPTY;

	/* (non-Javadoc)
	 * @see org.eclipse.ui.actions.ActionDelegate#selectionChanged(org.eclipse.jface.action.IAction, org.eclipse.jface.viewers.ISelection)
	 */
	public void selectionChanged(IAction action, ISelection sel) {
		if(sel instanceof IStructuredSelection)
			selection = (IStructuredSelection) sel;
		else 
			selection = StructuredSelection.EMPTY;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.actions.ActionDelegate#run(org.eclipse.jface.action.IAction)
	 */
	public void run(IAction action) {
		if(selection.isEmpty()) return;
		Object parent = selection.getFirstElement();
		Object toRefresh = parent;
		
		if(parent instanceof MapKeyTreeElem){
			TreeElem child = ((MapKeyTreeElem) parent).getChild();
			if(child==null){
				MapKeyTreeElem parentElem = (MapKeyTreeElem) parent;
				Type t = parentElem.getType();
				Object ob = load(t);
				TreeElemImpl newElem = TreeElemFactory.getInstance(parentElem, t, ob);
				if(newElem!=null){
					synchronized (DflPlugin.class) {
						parentElem.addChild(newElem);
						parentElem.update();
					}
					ViewsManager.refreshViews(toRefresh);	
					TreeElemPreview view = TreeElemPreview.getView();
					if(view!=null){
						view.selectionChanged(new DflSelectionChangedEvent(parentElem));
					}
				}
			}else{
				parent = ((MapKeyTreeElem) parent).getChild();
			}
		}
		
		if(parent instanceof TokenTreeElem){
			TokenTreeElem parentElem = (TokenTreeElem) parent;
			Type t = ((TokenTreeElem)parent).getType();
			Object ob = load(t);
			if(ob!=null){
				TreeElemImpl newElem = TreeElemFactory.getInstance(parentElem, t, ob);
				if(newElem!=null){
					synchronized (DflPlugin.class) {
						parentElem.setNewChild(newElem);
						parentElem.update();
					}
					ViewsManager.refreshViews(toRefresh);	
					TreeElemPreview view = TreeElemPreview.getView();
					if(view!=null){
						view.selectionChanged(new DflSelectionChangedEvent(newElem));
					}
				}
			}
		}else if(parent instanceof DataTreeElem){
			DataTreeElem elem = (DataTreeElem) parent;
			Type t = ((DataTreeElem)parent).getType();
			Object ob = load(t);
			if (ob != null) {
				try {
					synchronized (DflPlugin.class) {
						elem.load(ob);
					}
				} catch (Exception e) {
					DialogsManager.openErrorDialog(e);
					return;
				}
				ViewsManager.refreshViews(elem.getParent());
				TreeElemPreview view = TreeElemPreview.getView();
				if (view != null) {
					view.selectionChanged(new DflSelectionChangedEvent(elem));
				}
			}
		}
	}

	private Object load(Type t) {
		FileDialog dlg = new FileDialog(Display.getCurrent().getActiveShell(), SWT.SINGLE);
        
		IProject project = WorkbenchUtil.getCurrentProject();
		String projectPath = project.getLocation().toFile().getAbsolutePath();
		if(new File(projectPath + ProjectConstraints.PROJECT_DIR_DATA).exists()){ //$NON-NLS-1$
			dlg.setFilterPath(projectPath + ProjectConstraints.PROJECT_DIR_DATA); //$NON-NLS-1$
		}else{
			dlg.setFilterPath(projectPath);
		}
		
        // Change the title bar text
        dlg.setText(Messages.LoadContentAction_0);

        // null if user cancels
        String fileName = dlg.open();
        if (fileName != null) {
        	try {
        		return IODataManager.loadDataObject(fileName, t);
			} catch (Exception e) {
				try {
					if (TypeManager.isBinaryType(t) || (TypeManager.isAnyType(t) && Utils.isBinaryFile(fileName))) {
						return Utils.getBinaryFileContents(fileName);
					} else if (TypeManager.isStringType(t)	|| TypeManager.isAnyType(t)) {
						return Utils.getTextFileContents(fileName);
					} else {
						DialogsManager.openErrorDialog(e);
					}

				} catch (IOException e1) {
					DialogsManager.openErrorDialog(e);
				}
			}
        }
        return null;
	}
}
